package vengadores;

import java.io.InputStream;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.media.Manager;
import javax.microedition.media.MediaException;
import javax.microedition.media.Player;
import javax.microedition.midlet.*;

/**
 * Es el midlet. El objeto principal de la aplicación, que maneja la interacción de ésta última con el sistema. También maneja la música del juego y hace los cambios de pantalla que sean neceesarios.
 * @author Felipe Donato Arrazola Gómez
 * @author Jorge de Jesús Tinoco Huesca
 * @author Arturo Ayala Tello
 */
public class AppJuego extends MIDlet {

    private boolean creado; //Sirve para saber si es que el midlet ya está creado
    private Player p;
    private boolean reproduciendo, deseaReproducir;
    private boolean deseaVibracion = true;
    private Displayable actual;
    private AdminArchivos archivos;

    /**
     * Constructor de la clase de la aplicación
     */

    public AppJuego(){
        try {
            archivos = new AdminArchivos();
        } catch (IllegalAccessException ex) {
            ex.printStackTrace();
        }
    }

    /**
     * Método que inicializa la aplicación si está estaba en estado de pausa
     */
    public void startApp() {
        deseaReproducir = true;
        if (!creado){
            try {
                actual = new Pantalla(this, Pantalla.INICIO);
                Display.getDisplay(this).setCurrent(actual);
                creado = true;
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
     /**
     * Es el método que se manda llamar cuando hay una llamada de sistema o algo parecido que obstruye la aplicación.
     */
    public void pauseApp() {
    }

    /**
     * Destruye la aplicación para que sea terminada y se libere la memoria utilizada por ella.
     * @param unconditional si es true, la aplicación terminará sin ningún cuestionamiento, se puede forzar la terminación
     */
    public void destroyApp(boolean unconditional) {
        archivos.terminar();
        archivos = null;
    }

    /**
     * Es el método utilizado para cambiar de una fase a otra, cambiando la pantalla actual, por la pantalla enviada en el parámetro.
     * @param nuevo Es el Displayable que se desea desplegar en la pantalla.
     */

    public void ponerPantalla(Displayable nuevo) {
        //actual = null;
        actual = nuevo;
        //nuevo = null;
        Display.getDisplay(this).setCurrent(actual);
        System.out.println("mem "+Runtime.getRuntime().freeMemory());
        System.gc();
        System.out.println("mem2 "+Runtime.getRuntime().freeMemory());
    }

    /**
     * Se utiliza para obtener el Displayable que se encuentra en la pantalla.
     * @return objeto de tipo Displayable.
     */

    public Displayable getPantallaActual(){
        return actual;
    }
    /**
     * Se usa para que la música se reproduzca
     * @param archivo Es el archivo fuente del cual se cargará la música.
     * @throws Exception Si no se pudo cargar el archivo.
     */
    public void reproducir(String archivo) throws Exception {
            try {
                if(p!=null){
                    p.stop();
                    p.deallocate();
                    p=null;
                    reproduciendo = false;
                 }
                 InputStream datos = getClass().getResourceAsStream(archivo);
                 if(archivo.equalsIgnoreCase("reload.wav"))
                     p=Manager.createPlayer(datos,"audio/x-wav");
                 else{
                     p=Manager.createPlayer(datos,"audio/midi");
                     p.setLoopCount(-1);
                 }
                 p.realize();
                 p.prefetch();
                 p.start();
                 reproduciendo = true;
             }catch(Exception e){
                 e.printStackTrace();
             }
        }
     /**
     * Método que se usa para detener la música que se esté reproduciendo.
     */
    public void detenerMusica(){
        try {
            p.stop();
        } catch (MediaException ex) {
            ex.printStackTrace();
        }
        p.deallocate();
        p = null;
        reproduciendo = false;
    }
    /**
     * Utilizado para terminar la aplicación, cerrando la música y mandando los elementos de la aplicación a null.
     */
    public void terminar() {
        actual = null;
        if(reproduciendo)
            this.detenerMusica();
        destroyApp(true);
        notifyDestroyed();
    }

    /**
     * Método para saber si la música se está reproduciendo.
     * @return booleano que indica el estado de la música.
     */
    public boolean estaReproduciendo(){
        return reproduciendo;
    }

    /**
     * Método que nos dice si el usuario desea reproducir música
     * @return booleano que representa el deseo del usuario para reproducir música
     */

    public boolean deseaReproducir(){
        return deseaReproducir;
    }

    /**
     * Método que nos dice si el usuario desea vibración en el juego
     * @return booleano que representa el deseo por hacer vibrar al celular
     */

    public boolean deseaVibracion(){
        return deseaVibracion;
    }

    /**
     * Método que cambia el deseo del usuario para reproducir música
     * @param deseo es el deseo del usuario
     */
    public void cambiarDeseoRep(boolean deseo){
        deseaReproducir = deseo;
    }

    /**
     * Método que cambia el deseo del usuario para vibrar durante el juego
     * @param deseo es el deseo del usuario
     */
    public void cambiarDeseoVib(boolean deseo){
        deseaVibracion = deseo;
    }

    /**
     * Método que recupera de los archivos el punto de control
     * @return el punto de control donde estaba el personaje
     */
    public int getPuntoControl(){
        return archivos.getPuntoControl();
    }

    /**
     * Método que guarda el estado del juego donde se quedó el usuario
     * @param nivel es el nivel donde se quedó el juego
     * @param sexoPersonaje es el genero del heroe del juego
     * @param xPersonaje es la posición en x del último punto de control
     * @param yPersonaje es la posición en y del último punto de control
     * @param ptoControl es el punto de control donde se quedó el usuario
     * @param score es el puntaje que el usuario obtuvo
     * @param estaEnShooter nos dice si está en modo de Shooter o no
     */

    public void guardarJuego(int nivel, int sexoPersonaje, int xPersonaje, int yPersonaje, int ptoControl, int score, boolean estaEnShooter) {
        archivos.guardarJuego(nivel, sexoPersonaje, xPersonaje, yPersonaje, ptoControl, score,estaEnShooter);
    }

    /**
     * Método que regresa la posición en x en el último punto de control
     * @return la posición en x del último punto de control
     */

    public int getXPersonaje() {
        return archivos.getXPersonaje();
    }

    /**
     * Método que regresa la posición en y en el último punto de control
     * @return la posición en y del último punto de control
     */

    public int getYPersonaje() {
        return archivos.getYPersonaje();
    }

    /**
     * Método que regresa de los archivos el nivel donde se quedó el usuario
     * @return el nivel en el que estaba el usuario
     */
    public int getNivelGuardado() {
        return archivos.getNivel();
    }

    /**
     * Método que recupera de los archivos el genero del heroe que se guardó
     * @return el genero del heroe que se guardó
     */

    public int getSexoGuardado(){
        return archivos.getSexo();
    }

    /**
     * Método que recupera de los archivos el puntaje que generó el usuario
     * @return el puntaje guardado
     */

    public int getScoreGuardado(){
        return archivos.getScore();
    }

    /**
     * Método que recupera de los archivos si el usuario estaba en modo de Shooter o no
     * @return booleano que representa si estaba en Shooter o no
     */

    public boolean getEdoShooter(){
        return archivos.getEdoShooter();
    }

    /**
     * Método que recupera de los archivos los nombres de Los Mejores
     * @return un arreglo de Strings que contiene los nombres de Los Mejores
     */

    public String[] getNombresGuardados() {
        return archivos.getNombres();
    }

    /**
     * Método que recupera de los archivos los puntajes de Los Mejores
     * @return un arreglo de enteros que contiene los puntajes de Los Mejores
     */

    public int [] getPuntuaciones(){
        return archivos.getScores();
    }

    /**
     * Método que recupera de los archivos el puntaje temporal para manejo entre pantallas
     * @return entero que guarda el valor del puntaje temporal
     */

    public int getScoreTemp(){
        return archivos.getScoreTemp();
    }

    /**
     * Método que analiza los archivos para guardar el puntaje mandado y lo guarda temporalmente si el archivo es
     * candidato a ser guardado en Los Mejores
     * @param score es el puntaje generado
     * @return si el puntaje mandado es candidato para ser guardado en Los Mejores
     */

    public boolean analizar(int score){
        return archivos.analizar(score);
    }

    /**
     *Método que escribe en los archivos el puntaje y el nombre del usuario que logró entrar en Los Mejores
     * @param nombre es el nombre del usuario que generó los puntos
     * @param score es el puntaje que realizó el usuario
     */

    public void guardarScore(String nombre, int score) {
        archivos.guardarScore(nombre, score);
    }
}
